package tech.mhuang.pacebox.springboot.core.exception;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import tech.mhuang.pacebox.core.exception.BusinessException;
import tech.mhuang.pacebox.core.exception.ExceptionUtil;
import tech.mhuang.pacebox.springboot.protocol.Result;

import javax.servlet.http.HttpServletRequest;

/**
 * 通用异常拦截
 *
 * @author mhuang
 * @since 1.0.0
 */
@ControllerAdvice
public class CommonExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Value("${pacebox.exception.debug:false}")
    private Boolean debug;

    @Value("${system.error.message:服务器异常,请联系管理员}")
    private String systemErrorMessage;

    @Value("${not.support.error.message:不支持的请求方式}")
    private String notSupportedMessage;

    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Result<?> defaultErrorHandler(HttpServletRequest request, Exception e) {

        logger.error("---Exception Handler---Host {} invokes url {} ERROR: {}",
                request.getRemoteHost(), request.getRequestURL(), e.getMessage(), e);

        Result result = new Result<>();
        Integer code = Result.SYS_FAILD;
        String message, field = null;
        if (e instanceof BusinessException) {
            BusinessException business = (BusinessException) e;
            code = business.getCode();
            message = business.getMessage();
        } else if (e instanceof BindException) {
            field = ((BindException) e).getAllErrors().get(0).getCode();
            message = ((BindException) e).getAllErrors().get(0).getDefaultMessage();
        } else if (e instanceof MethodArgumentNotValidException) {
            field = ((MethodArgumentNotValidException) e).getBindingResult().getFieldError().getField();
            message = ((MethodArgumentNotValidException) e).getBindingResult().getFieldError().getDefaultMessage();
        } else if (e instanceof HttpRequestMethodNotSupportedException) {
            message = new StringBuilder(notSupportedMessage).append(request.getMethod()).toString();
        } else {
            message = systemErrorMessage;
        }
        result.setField(field);
        result.setCode(code);
        result.setMessage(message);
        if (debug) {
            result.setExceptionMsg(ExceptionUtil.getMessage(e));
        }

        return result;
    }
}
